Rendering Algorithms Final Report

cs 287 | fall '25 | jeff tedi

(#) inspiration

© Stanley Kubrick Productions / Metro-Goldwyn-Mayer

© Heyday Films / Esperanto Filmoj / Warner Bros. Pictures.

© Kojima Productions / Sony Interactive Entertainment

(#) features **1)** Parallelization with SmallThreadPool - 1 pt. Since rendering can be (and is almost always), a daunting process, parallelism is the first modificiation I made to darts. I parallelized the image synthesis loop using SmallThreadPool library. Instead of iterating over all pixels in a single nested loop, I partitioned independent blocks of pixels and distributed it across a collection of workers initialized to the number of hardware threads on my CPU (20 in my case). Doing so cuts down render time by ~3x as demonstrated here.
Unparallelized runtime: 4m:35s
Unparallelized runtime (1 thread, 100 spp): 4m:35s
Parallelized runtime: 1m:36s
Parallelized runtime (20 threads, 100 spp): 1m:36s
**2)** Rendering using the Discovery Cluster - 1 pt. We can still cut it down further thanks to Dartmouth's Discovery Cluster. I will skip over the details as implementation is "trivial" but I'm basically running darts on the cluster with significantly more computational resource. **3)** Intel's Open Image Denoiser - 2 pts. This one was relatively challenging to implement only because the relevant documentations provided for Ubuntu is obsolete (e.g. packages don't exist in apt search). Beyond that, it was a simple one-line function call once the library was wired up. I made a small helper denoise_with_oidn(Image3f &img) that wraps the API and we call it right before darts perform a save operation. I made clones of samplers inside each worker thread. Otherwise, our next1f/next2f() functions behave like a global randf(), effectively serializing the threads on a single sampler. I found 128 to be a good spp to get a denoised image without the artifacts we get when denoising a low spp image.
<figcaption>Reference</figcaption> <figcaption>Denoised (16 spp)</figcaption> <figcaption>Denoised (128 spp)</figcaption>

Fig. 1. At sufficiently low spp (e.g. 16 spp), you start to get the blotched look.

But for the sake of validation, we will render everything but the final render without this denoiser. **4)** Environment Map Emitter (with importance sampling) - 2 pts. At any given point in time, our surroundings are rarely a single area light; most illuminants are objects that reflect off of direct light sources. To "color" our scenes with such environments, I added support for environment maps that will act both as a visible background and light source. We importance sample this emitter w.r.t. luminance over a given pixel of the envmap image.

© Digital Illusions CE / Electronic Arts

**5)** Rough Conductor BSDF - 2 pts. Spacesuits (and many other everyday items, not that spacesuits are one) are shiny, but they are not actually smooth at the microscopic level. Instead, they're made of countless tiny perturbations with different orientations. Compared to a simple Phong or Blinn-Phong model, the microfacet formulation enforces energy conservation. Whereas a classic Blinn/Phong model just adds an arbitrary specular lobe on top of a diffuse term, a microfacet BRDF derives its specular term from the Trowbridge-Reitz GGX normal distribution function. Consequently, changing roughness only redistributes the same incoming energy over directions instead of creating extra light.
Blinn-Phong Rough Conductor

Fig. 2. As observed, our microfacet model preserves the "brightness" and consequently, it looks more like a proper rough metal.

**6)** Spectral Rendering - 8 pts. Although most imaging pipelines are built around RGB, it is a crude approximation of how light and materials actually behave. Many different spectra can collapse to the same RGB triplet, so compressing everything to three numbers throws away subtle visual information, especially under non-white illumination or when dispersion is involved. In my implementation, the path tracer operates directly in this spectral domain. Each camera ray carries a single wavelength λ sampled uniformly between 400 nm and 700 nm, and all computations are done as functions of λ. This adds one extra dimension to the Monte Carlo estimator and appears visually as colored noise at low sample counts. Only after tracing is complete does the Monte Carlo estimator converge to the XYZ tristimulus values defined by the CIE 1931 color matching functions which are then mapped to RGB using the sRGB matrix (D65 white point).
RGB Spectral Spectral (wavelength-dependent IOR)

Fig. 3. RGB vs spectral rendering vs wavelength-dependent IOR to demonstrate dispersion.

As expected, a wavelength-dependent IOR disperses rays going through our glass sphere and we get a slight magnification effect due to the different angles it refracts through. (#) final scene
Entangled

“Entangled” -- final render for the competition. This scene is inspired by BT-encounters in Death Stranding.

(#) acknowledgements Code/Theory: Most of my algorithms are derived from Physically Based Rendering - From Theory to Implementation by Matt Pharr, Wenzel Jakob, Greg Humphreys Hero Wavelength Spectral Sampling by Alexander Wilkie, Sehera Nawaz, Marc Droske, Andrea Weidlich, Johannes Hanika https://momentsingraphics.de/SpectralRenderingOverview.html Assets: 3D model of Franz Viehböck's Sokol Space Suit is courtesy of the Naturhistorisches Museum Wien https://zachfox.photography/stories/mirrors-edge-catalyst-ansel-360-stereo/#x https://sketchfab.com/3d-models/strand-1-4ca6639319a149d686d050a3f5ea3e02 https://www.thingiverse.com/thing:4039942 https://www.spacespheremaps.com/hdr-spheremaps/ (##) addenum: a stretch goal was to implement heterogeneous participating media to add fog on the surface. It would've paired well with the environment map.